﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace DataMgr.File
{
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    struct POSINFO
    {
        public UInt64 lluStart;          //起始位置
        public UInt64 lluLen;            //长度
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    ///文件头
    struct BDFHead
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public Byte[] btFlag;              // "_GLLL_"
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public Byte[] btDate;             // "日期"
        public UInt16 usVersion;          //文件版本号
        public UInt16 usNdaVer;          //原始文件版本号
        public POSINFO piChannelInfo;      /*通道信息  */
        public POSINFO piStepsData;        //工步节点所在位置
        public POSINFO piCycle1;          //按记录中的循环ID来区分的循环统计区的位置
        public POSINFO piCycle2;          //按每遇见一个充电工步来区分的循环统计区的位置
        public POSINFO piExtern;          //可扩展信息，DA读取时不用sizeof,考虑不同时期保存的DA文件此处长度不一致2019-3-5
        public POSINFO piStepsInfo;        //工步统计节点链所在位置
        public POSINFO piLogsInfo;          //日志统计节点链所在位置
        public POSINFO piRecordsInfo;     // 主通道记录所在位置
        public POSINFO piAxusInfo;         //辅助通道统计节点链的所在位置
        public POSINFO piAxuRecordsInfo;  // lluStart最后一条记录序号,lluLen表示一条记录数据的长度
        public float fSetCapG;           //活性物质质量
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1980)]
        public Byte[] biReservation;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    struct ChannelDeviceInfo
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string midIp;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string barcode;  //条码
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string midVer;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string xwjVer;
        public Byte devId;
        public Byte pallelCount;    //并联数
        public UInt16 chlId;
        public UInt32 testId;   //测试编号
    }

    //单条日志历史数据
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    struct SingleHisLogData
    {
        public int nRecordSeq;             //记录序号
        public UInt32 nRefTestSn;             //映射码 从1开始递增，表示主通道历史数据和通道日志之间的映射关系，该值对应主通道历史数据记录号
        public double dTestTime;               //UNIX时间戳，精度为毫秒
        public int nEvent;                 // 0-无效，1-完成，2-启动，3-暂停，4-继续，5-停止，6-跳转，7-断电，8-上电，9-中位机通讯故障，10-中位机通讯恢复，11-中位机重启，12-中位机缓冲满，13-辅助通道电压超下限，14-辅助通道电压超上限，15-辅助通道温度超下限，16-辅助通道温度超上限，17-系统状态错误，18-DC通讯故障，19-AC通讯故障，20-DC故障，21-AC故障，22-工步截至，23-巡检掉线保护
        public Int64 nEventValue;          // 0-无效；当事件为DC故障时，表示DC故障码；当事件为AC故障时，表示AC故障码
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    struct STEP_STATIS    //工步统计点
    {
        public UInt32 dwStepID;      // 工步序号 0~n
        public Byte btStepType;     // 工步类型
        public UInt32 nRecordsCount;     // 该工步记录总数
        public UInt64 dwTimeSection; // 工步总时间
        public UInt64 ullTimeOffset;   // 工步的时间偏移
                                       //
        public Byte bTimeOffsetHaveCalc;   //标识工步的时间偏移已计算
        public Byte bCapEndHaveCalc;        //标识终止容量是否已计算
                                     //
        public double dCap;             // 容量/mAh
        public double dEng;            // 能量/mWh
        public double dVolStart;   // 起始电压
        public double dVolEnd;     // 终止电压
        public double dTmpStart;   // 起始温度
        public double dTmpEnd; // 终止温度
        public double dCapEnd;     //终止容量
        public UInt32 dwFirstRecordIndex; // 对应本工步第一个记录在主通道记录数据区的索引位置  0开始
        public UInt32 dwLastRecordIndex; // 对应本工步最后一个记录在文件里的位置

        public UInt32 dwCycleID;          //循环ID，在统计循环时使用,并不表示该工步属于某一循环
        public UInt32 dwAxuLines;       //该工步有多少辅助通道行数
                                //vector < stNdaXStepAxu > axusInfo;//该工步对应的各个辅助通道的位置
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    //单条历史数据
    struct SingleHisDfData
    {
        public UInt32 dwTestSn;             // 数据序号,主键，从1开始
        public UInt64 recordTime;               // 记录时间,流程开始后的毫秒数
        public UInt64 stepTime;             // 工步时间,当前工步执行的毫秒数
        public double dTestTime;               //UNIX时间戳，精度为毫秒
        public UInt32 dwCycle;              // 循环序号 从1开始
        public UInt32 stepSeq;              // 工步序号
        public UInt32 stepID;                   // 工步号
        public Byte btStepType;                // 工步类型。
        public Int32 nVolt;                  // 电压 0.0001V
        public Int32 nCurr;                  // 电流 0.0001A
        public short nTempature;               // 温度 0.01℃
        public int nCap;                   // 容量。0.001Ah
        public UInt32 dwChargeCap;          // 充电容量。0.001Ah
        public UInt32 dwDisChargeCap;           // 放电容量。0.001Ah
        public int nEngSum;                // 能量  0.001kWh
        public UInt32 dwChargeEng;             // 充电能量  0.001kWh
        public UInt32 dwDisChargeEng;          // 放电能量  0.001kWh
        public short nInterRes;                // 内阻 0.01mΩ
        public int nTranState;             //前一状态到当前状态的转换标志
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    struct DInfo
    {
        public short nIndex;
        public double dValue;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    struct SingleInfo
    {
        public Byte btFlag;    //单体使能
        public Byte btCaseNo;  //单体箱号
        public short nIndex;   //单体编号
        public float fValue;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    public class BmsHisData
    {
        public UInt32 TestSn { get; set; }             // 数据序号,主键，从1开始
        public Byte Flag { get; set; }                   // BMS使能,0表示不使能,则没有BMS数据
        public UInt16 StDataCount { get; set; }  //统计数据个数
        public UInt16 VolCount { get; set; }    //单体电压个数
        public UInt16 TempCount{ get; set; }    //单体温度个数
        public UInt16 SelfCount { get; set; } 	//自定义值个数
        public Byte[] StData;
        public Byte[] VolData;
        public Byte[] TempData;
        public Byte[] SelfData;

    }
    //下发给中位机使用的结构体
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    public struct StopCond
    {
        public Byte endCond;       //截止条件类型
        public Byte endCondOp;     //运算符
        public double endCondValue;    //运算值
        public Byte relation;      //与或关系；或，与，与子项
        public Byte action;            //动作；下一步，保护，停止
    }
    //工步信息，第一版的
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    struct StepFileInfo
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
        public string szGuid;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string szCreator;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string szMark;
        public UInt64 uProtectState;//每一位表示下面对应的全局保护是否生效
        public double highVol;
        public double lowVol;
        public double highCurrent;
        public double lowCurrent;
        public double highPower;
        public double lowPower;
        public double highCap;
        public double lowCap;
        public double highTemp;
        public double lowTemp;//温度下限,*10
        public UInt32 uRecordState;//对应下面的全局记录条件是否生效
        public double timeInterval;
        public double volInterval;
        public double curInterval;
        public double platVol1;
        public double platVol2;
        public double platVol3;
        public double platErr;//平台误差,非负数
    }
    //工步信息，0x201
    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    struct BmsStepFileInfo
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)]
        public string szGuid;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string szCreator;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string szMark;
        public UInt64 uProtectState;//每一位表示下面对应的全局保护是否生效
        public double highVol;
        public double lowVol;
        public double highCurrent;
        public double lowCurrent;
        public double highPower;
        public double lowPower;
        public double highCap;
        public double lowCap;
        public double highTemp;
        public double lowTemp;//温度下限,*10
        public double highVolS;    //BMS单体电压上限
        public double lowVolS; //单体电压下限
        public double errVolS; //单体电压差
        public double highTempS;   //单体温度上限
        public double lowTempS;    //单体温度下限
        public double errTempS;    //单体温度差
        public UInt32 uRecordState;//对应下面的全局记录条件是否生效
        public double timeInterval;
        public double volInterval;
        public double curInterval;
        public double platVol1;
        public double platVol2;
        public double platVol3;
        public double platErr;//平台误差,非负数
    }
    public enum BDF_Version : ushort
    {
        BDF_Ver1 = 1000,
        BDF_Ver2 = 1001,
        BDF_Ver3 = 1002,
    }
    public enum STEP_Version : ushort
    {
        VERSION_STEP_FILE_1 = 100,
        VERSION_STEP_FILE_2 = 101,//2019-8-8增加延时时间
        VERSION_STEP_FILE_3 = 102,//2019-10-28 支持BMS的工步文件
    }
    ///循环区分类型
    enum CycleDivideKind : ushort
    {
        Cycle_CycleID = 1,             //记录中的循环ID来区分
        Cycle_ChargeStep = 2,         //按每遇到一个充电工步区分
        Cycle_DischargStep = 3,     //按每遇到一个放电工步区分
        Cycle_StartStep = 5           //按设置的起始工步与工步数量来区分
    }

    ///循环区分类型
    enum StepType : ushort
    {
        STEP_MODE_IDLE = 1,  //  搁置 
        STEP_MODE_I_CHARGE = 2,    //  恒流充电 
        STEP_MODE_U_CHARGE = 3,    //  恒压充电  
        STEP_MODE_POWER_CHARGE = 4,    //  恒功率充电
        STEP_MODE_IU_CHARGE = 5,     //  恒流恒压充电 
        STEP_MODE_I_UNCHARGE = 6,    //  恒流放电 
        STEP_MODE_U_UNCHARGE = 7,    //  恒压放电
        STEP_MODE_POWER_UNCHARGE = 8,    //  恒功率放电
        STEP_MODE_IU_UNCHARGE = 9,    //  恒流恒压放电
        STEP_MODE_IR_DCHARGE = 10,    //  恒阻放电 
        STEP_MODE_IR_CHARGE = 11,   //  恒阻充电 
        STEP_MODE_PULSE = 12,    //  脉冲
        STEP_MODE_HILL = 13,   //  斜坡
        STEP_MODE_RECYCLE = 0xFE,   //  循环  
        STEP_MODE_SIM_CHARGE = 14,   //  模拟工况
        STEP_MODE_Li_CHARGE = 15,   //  直流内阻测试
        STEP_MODE_FINISH = 0xFF

    }

    //各保护参数在位图内的位置
    public enum ProtectState : long
    {
        ePos_highVol = 0x01,//
        ePos_lowVol = 0x02,//
        ePos_highCurrent = 0x04,//			
        ePos_lowCurrent = 0x08,//
        ePos_highPower = 0x10,//
        ePos_lowPower = 0x20,//
        ePos_highCap = 0x40,//
        ePos_lowCap = 0x80,//
        ePos_highTempl = 0x100,//
        ePos_lowTempl = 0x200,//

        ePos_highVol_Single = 0x400,
        ePos_lowVol_Single = 0x800,//
        ePos_VolErr_Single = 0x1000,//
        ePos_highTemp_Single = 0x2000,
        ePos_lowTemp_Single = 0x4000,//
        ePos_TempErr_Single = 0x8000,//
    }
    //各记录参数在位图内的位置
    public enum RecordState : long
    {
        ePos_timeInterval = 0x01,//
        ePos_volInterval = 0x02,//
        ePos_curInterval = 0x04,//			
    }

    enum COND_PARA : long
    {
        COND_PARA_TIME = 0x01,  //(ms)
        COND_PARA_VOL,
        COND_PARA_CUR,
        COND_PARA_CAP,
        COND_PARA_NRG,
        COND_PARA_TEMP,
        COND_PARA_CHG_CAP,
        COND_PARA_DISCHG_CAP,
        COND_PARA_CHG_NRG,
        COND_PARA_DISCHG_NRG,
        COND_SINGLE_VOL = 0x010001,
        COND_SINGLE_MAXVOL = 0x010002,
        COND_SINGLE_MINVOL = 0x010005,
        COND_SINGLE_ERRVOL = 0x010008,
        COND_SINGLE_MAXTEMP = 0x010009,
        COND_SINGLE_MINTEMP = 0x01000c,
        COND_SINGLE_ERRTEMP = 0x01000f,
        COND_SINGLE_SOC ,
        COND_SINGLE_CUR ,
    }
    class DaFileElement
    {
        public const double SCALE_IU = 0.0001; //电流,电压  中位机协议数据*这个比例=DA协议数据
        public const double SCALE_TR = 0.01;       //温度,内阻
        public const double SCALE_CN = 0.001;   //容量,能量
        public const UInt32 MAGIC_NUM_STEP_FILE = 0xA2B0C1D9; //高级工步显示
        public const UInt32 MAGIC_NUM_STEP_FILE_STD = 0xA2B0C1D4; //标准工步显示
        //反序列化,得到类、结构体
        public static object RawDeserialize(byte[] rawdatas, Type anytype)
        {
            int rawsize = Marshal.SizeOf(anytype);
            if (rawsize > rawdatas.Length)
                return null;

            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.Copy(rawdatas, 0, buffer, rawsize);
            object retobj = Marshal.PtrToStructure(buffer, anytype);
            Marshal.FreeHGlobal(buffer);
            return retobj;
        }

        public static int SwitchStepType(ushort stepType)
        {
            switch ((StepType)stepType)
            {
                case StepType.STEP_MODE_I_CHARGE:
                case StepType.STEP_MODE_U_CHARGE:
                case StepType.STEP_MODE_POWER_CHARGE:
                case StepType.STEP_MODE_IU_CHARGE:
                case StepType.STEP_MODE_IR_CHARGE:
                    return 1;
                case StepType.STEP_MODE_I_UNCHARGE:
                case StepType.STEP_MODE_U_UNCHARGE:
                case StepType.STEP_MODE_POWER_UNCHARGE:
                case StepType.STEP_MODE_IU_UNCHARGE:
                case StepType.STEP_MODE_IR_DCHARGE:
                    return 0;
                default:
                    return  - 1;
            }
            return  - 1;
        }
    }
}
